package com.yunshipei.core.download.preview;

import android.net.Uri;
import android.text.TextUtils;

import com.yunshipei.core.common.XCloudException;
import com.yunshipei.core.model.FilePreviewConfig;
import com.yunshipei.core.model.HttpAuthModel;
import com.yunshipei.core.model.XDownloadModel;
import com.yunshipei.core.net.DocConvertApi;
import com.yunshipei.core.net.DownloadApi;
import com.yunshipei.core.net.EnterClient;
import com.yunshipei.core.net.NTLMAuthenticator;
import com.yunshipei.core.net.convert.JsonConverterFactory;

import org.json.JSONArray;
import org.json.JSONObject;
import org.reactivestreams.Publisher;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.SocketAddress;
import java.util.concurrent.TimeUnit;

import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.FlowableEmitter;
import io.reactivex.FlowableOnSubscribe;
import io.reactivex.functions.Function;
import okhttp3.FormBody;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;

public class FilePreview {
    private final OkHttpClient.Builder downloadClientBuilder = new OkHttpClient.Builder().connectTimeout(20 * 60, TimeUnit.SECONDS).readTimeout(20 * 60, TimeUnit.SECONDS).writeTimeout(20 * 60, TimeUnit.SECONDS);
    private final OkHttpClient.Builder uploadClientBuilder = new OkHttpClient.Builder().connectTimeout(20 * 60, TimeUnit.SECONDS).readTimeout(20 * 60, TimeUnit.SECONDS).writeTimeout(20 * 60, TimeUnit.SECONDS);

    private XDownloadModel xDownloadModel;
    private String downloadProxyIP = "";
    private int downloadProxyPort = 0;
    private HttpAuthModel httpAuthModel;
    private FilePreviewConfig filePreviewConfig;

    public FilePreview(XDownloadModel xDownloadModel, FilePreviewConfig filePreviewConfig, String downloadProxyIP, int downloadProxyPort, HttpAuthModel httpAuthModel) {
        this.xDownloadModel = xDownloadModel;
        this.filePreviewConfig = filePreviewConfig;
        this.downloadProxyIP = downloadProxyIP;
        this.downloadProxyPort = downloadProxyPort;
        this.httpAuthModel = httpAuthModel;
    }

    public Flowable<String> start() {
        String docServer = filePreviewConfig.getDocConvertServer();
        if (docServer.endsWith("/")) {
            docServer = docServer.substring(0, docServer.length() - 1);
        }
        final String finalDocServer = docServer;
        Flowable<JSONObject> flowable;
        if (filePreviewConfig.getType() == FilePreviewConfig.TYPE_ONLINE_PREVIEW) {
            flowable = Flowable.just(xDownloadModel).flatMap(new Function<XDownloadModel, Publisher<JSONObject>>() {
                @Override
                public Publisher<JSONObject> apply(XDownloadModel xDownloadModel) throws Exception {
                    String fileName = xDownloadModel.getFileName();
                    String convertType = "0";
                    if (fileName.endsWith(".pdf")) {
                        convertType = "14";
                    }
                    FormBody.Builder builder = new FormBody.Builder();
                    String cookie = xDownloadModel.getCookie();
                    if (!TextUtils.isEmpty(cookie)) {
                        builder.add("cookie", cookie);
                    }
                    builder.add("downloadUrl", xDownloadModel.getUrl()).add("convertType", convertType).add("isShowTitle", "0");
                    RequestBody requestBody = builder.build();
                    String filePreviewProxyIP = filePreviewConfig.getProxyIP();
                    int filePreviewProxyPort = filePreviewConfig.getProxyPort();
                    if (!TextUtils.isEmpty(filePreviewProxyIP) && filePreviewProxyPort > 0) {
                        SocketAddress sa = new InetSocketAddress(filePreviewProxyIP, filePreviewProxyPort);
                        //定义代理，此处的Proxy是源自java.net
                        Proxy proxy = new Proxy(Proxy.Type.HTTP, sa);
                        uploadClientBuilder.proxy(proxy);
                    }
                    OkHttpClient client = uploadClientBuilder.build();
                    return new Retrofit.Builder().client(client).baseUrl(finalDocServer).addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                            .addConverterFactory(JsonConverterFactory.create()).build().create(DocConvertApi.class).docServerConvert(requestBody);
                }
            });
        } else {
            flowable = Flowable.create(new FlowableOnSubscribe<Flowable<Response<ResponseBody>>>() {
                @Override
                public void subscribe(FlowableEmitter<Flowable<Response<ResponseBody>>> e) throws Exception {
                    final String cookieStr = xDownloadModel.getCookie();
                    final String userAgent = xDownloadModel.getUserAgent();
                    if (!TextUtils.isEmpty(cookieStr) || !TextUtils.isEmpty(userAgent)) {
                        downloadClientBuilder.addInterceptor(new Interceptor() {
                            @Override
                            public okhttp3.Response intercept(Chain chain) throws IOException {
                                Request.Builder builder = chain.request().newBuilder();
                                if (!TextUtils.isEmpty(cookieStr)) {
                                    builder.addHeader("Cookie", cookieStr);
                                }
                                if (!TextUtils.isEmpty(userAgent)) {
                                    builder.addHeader("User-Agent", userAgent);
                                }
                                return chain.proceed(builder.build());
                            }
                        });
                    }
                    //设置AD认证
                    if (httpAuthModel != null) {
                        downloadClientBuilder.authenticator(new NTLMAuthenticator(httpAuthModel.getUserName(), httpAuthModel.getPassword()));
                    }
                    if (!TextUtils.isEmpty(downloadProxyIP) && downloadProxyPort > 0) {
                        SocketAddress sa = new InetSocketAddress(downloadProxyIP, downloadProxyPort);
                        //定义代理，此处的Proxy是源自java.net
                        Proxy proxy = new Proxy(Proxy.Type.HTTP, sa);
                        downloadClientBuilder.proxy(proxy);
                    }
                    OkHttpClient okHttpClient = downloadClientBuilder.build();
                    EnterClient.getInstances().initSSLClient(okHttpClient);
                    String downloadUrl = xDownloadModel.getUrl();
                    Flowable<retrofit2.Response<ResponseBody>> downloadFlowable = null;
                    DownloadApi downloadApi = new Retrofit.Builder().client(okHttpClient).baseUrl("http://127.0.0.1:8080").addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build().create(DownloadApi.class);
                    String method = xDownloadModel.getMethod();
                    switch (method.toUpperCase()) {
                        case "GET":
                            downloadFlowable = downloadApi.get(downloadUrl);
                            break;
                        case "POST":
                            MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
                            JSONArray jsonArray = new JSONArray(xDownloadModel.getFormData());
                            for (int i = 0; i < jsonArray.length(); i++) {
                                JSONObject object = jsonArray.optJSONObject(i);
                                if (object == null) continue;
                                builder.addFormDataPart(object.optString("key"), object.optString("value"));
                            }
                            downloadFlowable = downloadApi.post(downloadUrl, builder.build());
                            break;
                    }
                    e.onNext(downloadFlowable);
                }
            }, BackpressureStrategy.BUFFER).flatMap(new Function<Flowable<Response<ResponseBody>>, Publisher<Response<ResponseBody>>>() {
                @Override
                public Publisher<retrofit2.Response<ResponseBody>> apply(Flowable<retrofit2.Response<ResponseBody>> responseFlowable) throws Exception {
                    return responseFlowable;
                }
            }).flatMap(new Function<retrofit2.Response<ResponseBody>, Publisher<JSONObject>>() {
                @Override
                public Publisher<JSONObject> apply(retrofit2.Response<ResponseBody> response) throws Exception {
                    final int code = response.code();
                    if (code == 200) {
                        String fileName = xDownloadModel.getFileName();
                        byte[] bytes = response.body().bytes();
                        String convertType = "0";
                        if (fileName.endsWith(".pdf")) {
                            convertType = "14";
                        }
                        RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), bytes);
                        RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM)
                                .addFormDataPart("convertType", convertType)
                                .addFormDataPart("htmlTitle", fileName)
                                .addFormDataPart("isShowTitle", "0")
                                .addFormDataPart("file", Uri.encode(fileName), fileBody).build();
                        String filePreviewProxyIP = filePreviewConfig.getProxyIP();
                        int filePreviewProxyPort = filePreviewConfig.getProxyPort();
                        if (!TextUtils.isEmpty(filePreviewProxyIP) && filePreviewProxyPort > 0) {
                            SocketAddress sa = new InetSocketAddress(filePreviewProxyIP, filePreviewProxyPort);
                            //定义代理，此处的Proxy是源自java.net
                            Proxy proxy = new Proxy(Proxy.Type.HTTP, sa);
                            uploadClientBuilder.proxy(proxy);
                        }
                        OkHttpClient client = uploadClientBuilder.build();
                        EnterClient.getInstances().initSSLClient(client);
                        return new Retrofit.Builder().client(client).baseUrl(finalDocServer).addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                                .addConverterFactory(JsonConverterFactory.create()).build().create(DocConvertApi.class).uploadConvert(requestBody);
                    } else {
                        return Flowable.error(new XCloudException("文件下载失败，错误状态码:" + code));
                    }
                }
            });
        }
        return flowable.flatMap(new Function<JSONObject, Publisher<String>>() {
            @Override
            public Publisher<String> apply(JSONObject jsonObject) throws Exception {
                String url = "";
                int status = jsonObject.optInt("result", 100);
                if (0 == status) {
                    JSONArray array = jsonObject.getJSONArray("data");
                    if (array != null) {
                        url = array.optString(0);
                    }
                }
                if (!TextUtils.isEmpty(url)) {
                    return Flowable.just(url);
                }
                return Flowable.error(new XCloudException(jsonObject.optString("message", "文件转换失败...")));
            }
        });
    }
}
